package titt.service.proxy;

import titt.TITTValues;
import titt.head.HeadFactory;
import titt.head.request.MethodHead;
import titt.head.request.Request;
import titt.head.request.RequestHead;
import titt.head.request.form.FormHead;
import titt.head.response.ResponseHead;
import titt.io.IOFactory;
import titt.io.socket.TITTSocket;
import titt.io.socket.in.SocketCloser;
import titt.key.KeyFactory;
import titt.key.TITTKey;
import titt.service.content.NuderRequest;
import titt.service.content.NuderResponse;
import titt.service.invoke.AdvancedMethodInvoker;
import titt.type.Type;
import titt.type.TypedObject;
import titt.util.ArrayUtil;

public class NuderInvoker implements AdvancedMethodInvoker {

	private final TITTKey key;
	
	public NuderInvoker(String... tokens) {
		key = KeyFactory.createKey(tokens);
	}
	
	
	@Override
	public TypedObject call(Type ret, String name, TypedObject... args) throws Exception {
		return call(name, args);
	}

	@Override
	public TypedObject call(String name, TypedObject... args) throws Exception {
		
		TITTSocket ts = IOFactory.createTITTSocket();
		
		if(args.length > 0 && args[args.length-1].getType().equals(new Type(NuderRequest.class))) {
			
			NuderRequest nuderReq = args[args.length-1].getObject();
			
			TypedObject[] urlargs = new TypedObject[args.length-1];	
			ArrayUtil.copyTo(args, 0, urlargs, 0, urlargs.length);
			
			RequestHead req = new Request(TITTValues.POST, key.asKeyString(), HeadFactory.EMPTY);
			MethodHead m = new MethodHead(name, urlargs, new TypedObject[0], req);
			
			ts.getHeadWriter().writeHead(new FormHead(nuderReq.getLength(), nuderReq.getBoundary(), m));

			nuderReq.writeTo(ts.getOutputStream());
			
		}
		else {
			RequestHead req = new Request(TITTValues.GET, key.asKeyString(), HeadFactory.EMPTY);
			ts.getHeadWriter().writeHead(new MethodHead(name, args, new TypedObject[0], req));
		}
		ts.getOutputStream().flush();
		
		ResponseHead resp = new ResponseHead(ts.getHeadReader().readHead());
		
		return new TypedObject(new Type(NuderResponse.class), new NuderResponse(resp, new SocketCloser(ts, ts.getInputStream())));
	}

}
